import math
import os
from datetime import datetime, timedelta
# import matplotlib
# matplotlib.use('Agg')  # 切换到无 GUI 后端
import matplotlib.dates as mdates
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

from PIL import Image

# 设置字体以支持中文
plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体
plt.rcParams['axes.unicode_minus'] = False  # 解决保存图像是负号'-'显示为方块的问题

# 颜色映射
# colors = {
#     0: '#000000',# 黑色
#     1: '#FF0000',# 红色
#     2: '#FF1493',# 粉红
#     3: '#FF34B3',# 桃红
#     4: '#FF3E96',# 粉紫
#     11: '#CD00CD',# 紫罗兰
#     12: '#D15FEE',# 粉紫
#     13: '#7D26CD',# 紫
#     14: '#4F4F4F',# 灰色
#     15: '#0000FF',# 蓝色
#     16: '#00FFFF',# 青色
#     21: '#228B22',# 绿色
#     22: '#B8860B',# 橙色
#     23: '#A0522D',# Sienna
#     24: '#FFA500',# 橙色
#     25: '#00C5CD',# 青色
#     26: '#66CDAA'# Aquamarine
# }
colors = {
    0: (0, 100, 0),       # 深绿色
    1: (0, 0, 255),       # 蓝色
    2: (139, 0, 0),       # 深红色
    3: (75, 0, 130),      # 深紫色
    4: (139, 69, 19),     # 深棕色
    7: (0, 69, 139),     # 深
    8: (0, 69, 19),     # 深
    10: (139, 139, 19),     # 深
    11: (205, 133, 63),    # 深橙色
    12: (0, 105, 105),     # 深青色
    13: (139, 0, 139),     # 深洋红色
    14: (40, 40, 40),      # 深灰色
    15: (85, 107, 47),     # 深橄榄绿
    16: (0, 105, 148),     # 深海蓝
    21: (255, 0, 139),     # 深酒红
    22: (85, 65, 0),       # 深咖啡色
    23: (22, 55, 22),     # 深苔藓绿
    24: (0, 0, 128),       # 深蓝色
    25: (0, 206, 209),    # 青色
    26: (102, 205, 170)   # Aquamarine
}


class ShowTimeDuration:
    def __init__(self):
        self.path = ''
        self.data = {}
        self.car_data = {}
        self.p85 = None
        self.p15 = None
        self.new_data = {}

    def read_file(self, path):
        self.path = path
        self.get_data()
        self.show(flag=False)
        self.show(flag=True)
        self.clear()

    def read_file2(self, path):
        self.path = path
        self.get_data2()
        self.show2(flag=False)
        self.show2(flag=True)
        self.clear()

    def read_file2_true(self, path, true_time_list):
        self.path = path
        self.get_data2()
        self.show2_true(true_time_list, flag=False)
        self.show2_true(true_time_list, flag=True)
        self.clear()

    def show(self, flag=False):

        if flag:
            k = 1
            v = self.data[k]
            duration_seconds = []
            times_keys = list(v.keys())
            times = [datetime.strptime(time, '%H:%M') for time in times_keys]
            for key, value in v.items():
                duration_seconds.append(value['duration_seconds'])
            data = {
                'x': times,
                'y': duration_seconds
            }

            plt.scatter(data['x'], data['y'], color=[c / 255 for c in colors[k]], label='车型：' + str(k))  # 绘制散点图
        else:
            for k, v in self.data.items():
                duration_seconds = []
                times_keys = list(v.keys())
                times = [datetime.strptime(time, '%H:%M') for time in times_keys]
                for key, value in v.items():
                    duration_seconds.append(value['duration_seconds'])
                data = {
                    'x': times,
                    'y': duration_seconds
                }

                plt.scatter(data['x'], data['y'], color=[c / 255 for c in colors[k]], label='车型：' + str(k))  # 绘制散点图

        # 设置X轴为每1小时一个标记
        ax = plt.gca()  # 获取当前的Axes
        fig = ax.figure
        fig.set_size_inches(20, 12)  # 宽度为10英寸，高度为6英寸
        # ax.xaxis.set_major_locator(mdates.HourLocator(interval=1))  # 每1小时一个主要刻度
        ax.xaxis.set_major_locator(mdates.MinuteLocator(byminute=[0, 30], interval=1))  # 每半小时一个主要刻度
        ax.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M'))  # 设置时间格式
        plt.gcf().autofmt_xdate()  # 自动调整X轴日期标签的格式

        # 设置Y轴每隔10进行显示
        y_min, y_max = ax.get_ylim()  # 获取当前Y轴的最小值和最大值
        # 找到最接近y_min但不大于y_min的10的倍数
        start = np.floor(y_min / 20) * 20
        # 找到最接近y_max但不小于y_max的10的倍数
        end = np.ceil(y_max / 20) * 20
        plt.yticks(np.arange(start, end + 1, 20))  # 设定Y轴的刻度间隔为10，并确保是整十

        # 添加标签和标题
        ax.set_xlabel('时间')
        ax.set_ylabel('通行时间（秒）')
        if flag:
            ax.set_title('小客车通行散点图')
        else:
            ax.set_title('所有车型通行散点图')
        ax.legend(loc='upper right')

        # # 显示图表
        # plt.show()

        # 保存图表到文件
        output_dir = os.path.join(os.path.dirname(self.path), 'png')
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
        file_name = os.path.basename(self.path).split('.')[0]
        if flag:
            output_filename = os.path.join(output_dir, file_name + '_car.png')
        else:
            output_filename = os.path.join(output_dir, file_name + '_all.png')
        plt.savefig(output_filename, dpi=200)
        # 关闭图表以释放内存
        plt.close()

    def show2(self, flag=False):

        if flag:
            k = 1
            v = self.data[k]
            duration_seconds = []
            times_keys = list(v.keys())
            times = [datetime.strptime(time, '%H:%M') for time in times_keys]
            for key, value in v.items():
                duration_seconds.append(value['new_seconds'])
            data = {
                'x': times,
                'y': duration_seconds
            }
            # 绘制散点图
            plt.scatter(data['x'], data['y'], color=[c / 255 for c in colors[k]], label='车型：' + str(k), s=10)
            # 绘制85分位数线
            plt.axhline(y=self.new_data[k]["85"], color='r', linestyle='--', label='85分位线')
            # 绘制15分位数线
            # plt.axhline(y=self.new_data[k]["15"], color='g', linestyle='--', label='0分位线')
            # 绘制平均数线
            # plt.axhline(y=self.new_data[k]["20"], color='y', linestyle='--', label='平均值线')
            plt.axhline(y=20, color='g', linestyle='--', label='20线')
            plt.axhline(y=60, color='y', linestyle='--', label='60线')
            xlim = plt.xlim()
            # 在水平线旁添加文本，选择靠近左边界的位置放置文本
            avg_time_str = str(int(self.new_data[k]["value"])) + "秒"
            plt.text(xlim[0], self.new_data[k]["40"], avg_time_str, verticalalignment='center', color='black')
        else:
            for k, v in self.data.items():
                duration_seconds = []
                times_keys = list(v.keys())
                times = [datetime.strptime(time, '%H:%M') for time in times_keys]
                for key, value in v.items():
                    # print(value)
                    duration_seconds.append(value['new_seconds'])
                data = {
                    'x': times,
                    'y': duration_seconds
                }
                # print(data)
                # 绘制散点图
                plt.scatter(data['x'], data['y'], color=[c / 255 for c in colors[k]], label='车型：' + str(k), s=10)

            # 绘制85分位数线
            plt.axhline(y=self.new_data[1]["85"], color='r', linestyle='--', label='85分位线')
            plt.axhline(y=20, color='g', linestyle='--', label='20线')
            plt.axhline(y=60, color='y', linestyle='--', label='60线')
            xlim = plt.xlim()
            # 在水平线旁添加文本，选择靠近左边界的位置放置文本
            avg_time_str = str(int(self.new_data[1]["value"])) + "秒"
            plt.text(xlim[0], self.new_data[1]["40"], avg_time_str, verticalalignment='center', color='black')

        # 设置X轴为每1小时一个标记
        ax = plt.gca()  # 获取当前的Axes
        fig = ax.figure
        fig.set_size_inches(20, 12)  # 宽度为10英寸，高度为6英寸
        # ax.xaxis.set_major_locator(mdates.HourLocator(interval=1))  # 每1小时一个主要刻度
        ax.xaxis.set_major_locator(mdates.MinuteLocator(byminute=[0, 30], interval=1))  # 每半小时一个主要刻度
        ax.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M'))  # 设置时间格式
        k = list(self.data.keys())[0]
        day = datetime.strptime(list(self.data[k].keys())[0], '%H:%M:%S')
        start_time = day.replace(hour=0, minute=0, second=0, microsecond=0)
        end_time = day.replace(hour=23, minute=59, second=59, microsecond=999999)
        ax.set_xlim(start_time, end_time)
        plt.gcf().autofmt_xdate()  # 自动调整X轴日期标签的格式
        plt.ylim(0, 200)
        # 设置Y轴刻度，每隔20显示一个
        yticks = np.arange(0, 201, 20)  # 生成从0到200（包括200），步长为20的数组
        plt.yticks(yticks)
        # 可选：添加网格线以提高可读性
        plt.grid(True, which='both', linestyle='--', linewidth=0.5)

        # 添加标签和标题
        ax.set_xlabel('时间')
        ax.set_ylabel('通行时间（秒）')
        if flag:
            ax.set_title('小客车通行散点图')
        else:
            ax.set_title('所有车型通行散点图')
        ax.legend(loc='upper right')

        # # 显示图表
        # plt.show()

        # 保存图表到文件
        output_dir = os.path.join(os.path.dirname(self.path), 'png')
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
        file_name = os.path.basename(self.path).split('.')[0]
        if flag:
            output_filename = os.path.join(output_dir, file_name + '_car.png')
        else:
            output_filename = os.path.join(output_dir, file_name + '_all.png')
        plt.savefig(output_filename, dpi=200)
        # 关闭图表以释放内存
        plt.close()

    def show2_true(self, true_time_list, flag=False):

        if flag:
            k = 1
            v = self.data[k]
            duration_seconds = []
            times_keys = list(v.keys())
            times = [datetime.strptime(time, '%H:%M:%S') for time in times_keys]
            for key, value in v.items():
                duration_seconds.append(value['new_seconds'])
            data = {
                'x': times,
                'y': duration_seconds
            }
            # 绘制散点图
            plt.scatter(data['x'], data['y'], color=[c / 255 for c in colors[k]], label='车型：' + str(k), s=10)
            # 绘制85分位数线
            plt.axhline(y=self.new_data[k]["85"], color='r', linestyle='--', label='85分位线')
            # 绘制15分位数线
            # plt.axhline(y=self.new_data[k]["15"], color='g', linestyle='--', label='0分位线')
            # 绘制平均数线
            # plt.axhline(y=self.new_data[k]["20"], color='y', linestyle='--', label='平均值线')
            plt.axhline(y=20, color='g', linestyle='--', label='20线')
            plt.axhline(y=60, color='y', linestyle='--', label='60线')
            xlim = plt.xlim()
            # 在水平线旁添加文本，选择靠近左边界的位置放置文本
            avg_time_str = str(int(self.new_data[k]["value"])) + "秒"
            plt.text(xlim[0], self.new_data[k]["40"], avg_time_str, verticalalignment='center', color='black')
        else:
            for k, v in self.data.items():
                duration_seconds = []
                times_keys = list(v.keys())
                times = [datetime.strptime(time, '%H:%M:%S') for time in times_keys]
                for key, value in v.items():
                    # print(value)
                    duration_seconds.append(value['new_seconds'])
                data = {
                    'x': times,
                    'y': duration_seconds
                }
                # print(data)
                # 绘制散点图
                plt.scatter(data['x'], data['y'], color=[c / 255 for c in colors[k]], label='车型：' + str(k), s=10)

            # 绘制85分位数线
            plt.axhline(y=self.new_data[1]["85"], color='r', linestyle='--', label='85分位线')
            plt.axhline(y=20, color='g', linestyle='--', label='20线')
            plt.axhline(y=60, color='y', linestyle='--', label='60线')
            xlim = plt.xlim()
            # 在水平线旁添加文本，选择靠近左边界的位置放置文本
            avg_time_str = str(int(self.new_data[1]["value"])) + "秒"
            plt.text(xlim[0], self.new_data[1]["40"], avg_time_str, verticalalignment='center', color='black')

        for i in range(len(true_time_list["true_value_list"])):
            x1_line = true_time_list["true_value_list"][i][:5]
            x_1 = datetime.strptime(x1_line, '%H:%M')
            plt.axvline(x=x_1, color='black', linestyle='--')
        for i in range(len(true_time_list["detection_value_list"])):
            x1_line = true_time_list["detection_value_list"][i]
            x_1 = datetime.strptime(x1_line, '%H:%M')
            plt.axvline(x=x_1, color='green', linestyle='--')

        # 设置X轴为每1小时一个标记
        ax = plt.gca()  # 获取当前的Axes
        fig = ax.figure
        fig.set_size_inches(20, 12)  # 宽度为10英寸，高度为6英寸
        # ax.xaxis.set_major_locator(mdates.HourLocator(interval=1))  # 每1小时一个主要刻度
        ax.xaxis.set_major_locator(mdates.MinuteLocator(byminute=[0, 30], interval=1))  # 每半小时一个主要刻度
        ax.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M'))  # 设置时间格式
        # 设置X轴时间范围固定为00:00到23:59
        k = list(self.data.keys())[0]
        day = datetime.strptime(list(self.data[k].keys())[0], '%H:%M:%S')
        start_time = day.replace(hour=0, minute=0, second=0, microsecond=0)
        end_time = day.replace(hour=23, minute=59, second=59, microsecond=999999)
        ax.set_xlim(start_time, end_time)
        plt.gcf().autofmt_xdate()  # 自动调整X轴日期标签的格式
        plt.ylim(0, 200)
        # 设置Y轴刻度，每隔20显示一个
        yticks = np.arange(0, 201, 20)  # 生成从0到200（包括200），步长为20的数组
        plt.yticks(yticks)
        # 可选：添加网格线以提高可读性
        plt.grid(True, which='both', linestyle='--', linewidth=0.5)

        # 添加标签和标题
        # ax.set_xlabel('时间')
        ax.set_ylabel('通行时间（秒）')
        if flag:
            ax.set_title('小客车通行散点图')
        else:
            ax.set_title('所有车型通行散点图')
        ax.legend(loc='upper right')

        # # 显示图表
        # plt.show()

        # 保存图表到文件
        output_dir = os.path.join(os.path.dirname(self.path), 'png')
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
        file_name = os.path.basename(self.path).split('.')[0]
        if flag:
            output_filename = os.path.join(output_dir, file_name + '_car.png')
        else:
            output_filename = os.path.join(output_dir, file_name + '_all.png')
        plt.savefig(output_filename, dpi=200, bbox_inches='tight', transparent=False)
        # 关闭图表以释放内存
        plt.close()

    def get_data(self):
        df_up = pd.read_csv(self.path)
        data0 = df_up.to_dict(orient='records')
        self.data = {}
        for i in range(len(data0)):
            time = data0[i]['transtime_down'].split(' ')[1][:5]
            ctype = data0[i]['feevehicletype']
            if ctype not in self.data:
                self.data[ctype] = {}

            self.data[ctype][time] = {
                "vlp": data0[i]['vlp'],
                "duration_seconds": data0[i]['duration_seconds']
            }

    def get_data2(self):
        df_up = pd.read_csv(self.path)
        data = df_up.to_dict(orient='records')
        self.data = {}
        for i in range(len(data)):
            time = data[i]['transtime_down'].split(' ')[1][:8]
            ctype = data[i]['feevehicletype']
            if ctype not in self.data:
                self.data[ctype] = {}

            self.data[ctype][time] = {
                "vlp": data[i]['vlp'],
                "duration_seconds": data[i]['duration_seconds']
            }

        for key, value in self.data.items():
            # print("k", key)
            value_data = [sub_dict["duration_seconds"] for sub_key, sub_dict in value.items()]
            # --------------------***计算85分位数,计算中位数***--------------------------------
            filtered_data = np.array(value_data)
            self.p85 = np.percentile(filtered_data, 85)
            self.p15 = np.percentile(filtered_data, 0)
            if len(value_data) <= 10:
                filtered_values = value_data
            else:
                filtered_values = [x for x in value_data if self.p15 < x < self.p85]
            # 如果有符合条件的元素，则计算平均值
            if filtered_values:
                # average_value = sum(filtered_values) / len(filtered_values)
                # print('平均值', average_value)
                # 计算过滤后的数据的中位数作为最优值
                optimal_value = np.median(filtered_values)
                # print(f"无异常数据的最优值 (中位数): {optimal_value}")
                average_value = optimal_value

                self.new_data[key] = {
                    "85": min(round(self.p85/average_value*40), 200),
                    "15": min(round(self.p15 / average_value * 40), 200),
                    "40": 40,
                    "value": average_value
                }
                for key1, value1 in value.items():
                    d = value1["duration_seconds"]
                    self.data[key][key1]["new_seconds"] = min(round(d/average_value*40), 200)
            self.p85 = None
            self.p15 = None


    def clear(self):
        self.data = {}
        self.car_data = {}
        self.path = ''


if __name__ == '__main__':

    name = "G004251002000620010,G004251001000320010-20240404"
    path0 = r'D:\GJ\项目\事故检测\output\邻垫高速'
    path = os.path.join(path0, name, 'time_duration_data.csv')

    showTimeDuration = ShowTimeDuration()
    showTimeDuration.read_file(path)
